package com.vv.tools.modules.utils.domain.service.impl;

import com.vv.tools.common.util.HttpClient;
import com.vv.tools.modules.utils.domain.model.CurlRequestBO;
import com.vv.tools.modules.utils.domain.service.CurlService;

import jakarta.annotation.Resource;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

/**
 * @author wen.li
 */
@Service
public class CurlServiceImpl implements CurlService {

    @Resource
    private HttpClient httpClient;

    private static void sleep(CurlRequestBO bo) {
        if (null == bo.getSleep() || bo.getSleep() <= 0) {
            return;
        }

        try {
            TimeUnit.SECONDS.sleep(bo.getSleep());
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public List<String> curl(CurlRequestBO bo) {
        String httpMethod = bo.getMethod();
        AtomicReference<String> url = new AtomicReference<>(parseUrl(bo.getUrl(), bo.getGlobalVariables()));
        AtomicReference<Map<String, String>> headerMap = new AtomicReference<>(parseHeader(bo.getHeaders(), bo.getGlobalVariables()));
        AtomicReference<String> requestBody = new AtomicReference<>(parseBody(bo.getBody(), bo.getGlobalVariables()));

        List<String> list = new ArrayList<>();
        if (CollectionUtils.isEmpty(bo.getBatchData())) {
            String response = httpClient.execute(httpMethod, url.get(), headerMap.get(), requestBody.get());
            String parseResponse = parseResponse(response, bo.getHandleResponse());
            list.add(parseResponse);
        } else {
            bo.getBatchData().forEach(v -> {
                url.set(parseUrl(url.get(), v));
                headerMap.set(parseHeader(headerMap.get(), v));
                requestBody.set(parseBody(requestBody.get(), v));
                String response = httpClient.execute(httpMethod, url.get(), headerMap.get(), requestBody.get());
                String parseResponse = parseResponse(response, bo.getHandleResponse());
                list.add(parseResponse);
                sleep(bo);
            });
        }
        return list;
    }

    private String parseResponse(String response, Map<String, String> handleResponse) {
        if (MapUtils.isEmpty(handleResponse)) {
            return response;
        }
        String result = response;
        for (Map.Entry<String, String> entry : handleResponse.entrySet()) {
            Matcher matcher = Pattern.compile(entry.getKey()).matcher(result);
            if (matcher.find()) {
                return matcher.replaceAll(entry.getValue());
            }
        }
        return result;
    }


    private String parseBody(String body, Map<String, String> globalVariables) {
        return parseVariable(body, globalVariables);
    }

    private Map<String, String> parseHeader(Map<String, String> header, Map<String, String> globalVariables) {
        Map<String, String> map = new HashMap<>();
        header.forEach((k, v) -> map.put(parseVariable(k, globalVariables), parseVariable(v, globalVariables)));
        return map;
    }

    private String parseUrl(String url, Map<String, String> globalVariables) {
        return parseVariable(url, globalVariables);
    }

    private String parseVariable(String str, Map<String, String> globalVariables) {
        if (StringUtils.isBlank(str) || !str.contains("{") || !str.contains("}") || MapUtils.isEmpty(globalVariables)) {
            return str;
        }
        String result = str;
        for (Map.Entry<String, String> entry : globalVariables.entrySet()) {
            result = result.replace("{" + entry.getKey() + "}", entry.getValue());
        }
        return result;
    }

}
